/*
 * @Author: Jone XIn
 * @Date: 2022-01-10 23:22:36
 * @LastEditTime: 2022-01-28 19:54:21
 * @Description: webSokcet 客户端
 */
'use strict'

const webSocket = require('nodejs-websocket');
const { web_socket_config } = require('../config.json');
const fs = require('fs-extra');
const queue = require('queue');
const { handProjectPath, createFileAbsolute } = require('../utils/tools');
const Watcher = require('./watcher');
class WsClient {

    syncInfo = {};
    watcher = null;



    constructor(ip, port, callback) {
        this.writeFileTaskQueue = queue({ concurrency: 1, autostart: true });
        this.ip = ip;
        this.port = port;
        this.con_key = ''

        this.client = webSocket.connect(`ws://${ip}:${port}`, () => {
            console.log(`连接: ws://${ip}:${port} 成功!`);
            this.client.on('text', (text) => {
                this.resetHeartCheck();
                this.handText(JSON.parse(text));
            })

            this.client.on('error', err => {
                console.log(err);
                this.client.close();
            })

            this.client.on('close', (code, msg) => {
                console.log(`连接关闭:${code},错误信息:${msg}`);
                this.reconnect();
            })

            this.heartCheck();
            callback(true);
        })
    }
    // 所有消息的接受入口，分配不同消息到不同的处理函数
    handText(data) {
        switch (data.cmd) {
            case 'news':
                this.handNews(data.content);
                break;
            case 'heart':
                break;
            case 'reply':
                console.log(data);
                break;
            case 'regist': {
                this.handCreateWatcher(data.content);
                console.log(data.content.key);
                break;
            }
            default:
                console.log(data);
                break;
        }
    }
    handCreateWatcher(content) {
        const { project_name, project_path, sync_id } = this.syncInfo;
        this.watcher = new Watcher(project_name, project_path, sync_id, this, content);
    }
    /**
     * 处理接收到的信息任务
     * @param {Object} data
     * {
     *      desc: '描述',
     *      project_name:'项目名',
     *      project_path:'项目绝对路径',
     *      data:'buffer',
     *      filePath:'文件路径'
     * }
     */
    handNews(fileInfo) {
        // 转换成本机的文件地址
        const aimFilePath = handProjectPath(fileInfo)
        console.log(`目标地址:${aimFilePath}`);
        this.handNewsType(aimFilePath, fileInfo);
    }
    // 重连
    reconnect() {
        this.timmer && clearTimeout(this.timmer);
        this.timmer = setTimeout(() => {
            new WsClient(this.ip, this.port);
        }, 1000);
    }
    // 心跳包
    heartCheck() {
        this.heartTimer = setInterval(() => {
            this.client.sendText(JSON.stringify({ cmd: "heart", content: {} }))
        }, 4000);
    }
    // 重置心跳
    resetHeartCheck() {
        this.heartTimer && clearInterval(this.heartTimer);
        this.heartCheck();
    }
    /**
     * 注册房间号
     * @param {Object} data
     * {
     *      sync_id: '',
     *      project_name: '',
     *      project_path: ''
     * }
     */
    registRoomId(data) {
        try {
            this.syncInfo = data;
            const registData = {
                cmd: 'sync_id',
                content: {
                    desc: '房间号',
                    sync_id: data.sync_id,
                    project_name: data.project_name,
                    project_path: data.project_path,
                    m_id: data.m_id
                }
            }
            this.client.send(JSON.stringify(registData));
            return true;
        } catch (_) {
            console.log(_);
            return false;
        }
    }
    /**
     * 发送文件更改信息
     * @param {Object} data
     * {
     *      sync_id: '房间号',
     *      data: 'buffer',
     *      filePath: '',
     *      type: 'update'
     * }
     */
    sendNewsText(fileInfo) {
        try {
            this.client.send(JSON.stringify({ cmd: 'news', content: fileInfo }));
            return true;
        } catch (_) {
            console.log(_);
            return false;
        }
    }

    /**
     * 处理不同的消息类型
     * @param {Object} fileInfo
     */
    handNewsType(filePath, fileInfo) {
        // 任务push进队列
        this.writeFileTaskQueue.push((cb) => {
            this.upDateFileInfo({ filePath, data: fileInfo.data, type: fileInfo.type });
            cb();
        });
    }

    /**
     * 文件信息
     * @param {Object} fileInfo
     */
    upDateFileInfo(fileInfo) {
        try {
            console.log(fileInfo);
            // 创建类
            if (fileInfo.type == 'update' || fileInfo.type == 'addFile' || fileInfo.type == 'addDir') {
                // 保证路径已经创建了
                const status = createFileAbsolute(fileInfo.filePath);
                if (status) {
                    console.log(fileInfo);
                    fs.writeFile(fileInfo.filePath, Buffer.from(fileInfo.data.data ? fileInfo.data.data : []), 'binary', err => {
                        if (err) console.log(err);
                    })
                    console.log(`${fileInfo.filePath}写入成功`);
                    return;
                }
                console.log('路径创建失败!');
                return;
            } else {
                // 删除类
                fs.removeSync(fileInfo.filePath);
            }

        } catch (_) {
            console.log(_);
        }
    }
}

module.exports = WsClient;
// WsClient.getInstance(web_socket_config.ip, web_socket_config.port);
